#include "common/logger/logger.h"

namespace common {
namespace logger {

// ConsoleSink 实现
void ConsoleSink::write(const LogEntry& entry) {
    // 设置不同日志级别的颜色
    const char* color = "";
    switch (entry.level) {
        case LogLevel::DEBUG:   color = "\033[36m"; break; // 青色
        case LogLevel::INFO:    color = "\033[32m"; break; // 绿色
        case LogLevel::WARNING: color = "\033[33m"; break; // 黄色
        case LogLevel::ERROR:   color = "\033[31m"; break; // 红色
        case LogLevel::FATAL:   color = "\033[35m"; break; // 紫色
    }
    
    std::cout << color 
              << "[" << Logger::formatTimestamp(entry.timestamp) << "] "
              << "[" << Logger::levelToString(entry.level) << "] "
              << "[" << entry.threadId << "] "
              << entry.message 
              << "\033[0m" << std::endl;
}

// FileSink 实现
FileSink::FileSink(const std::string& filename) {
    file_.open(filename, std::ios::out | std::ios::app);
    if (!file_.is_open()) {
        throw std::runtime_error("无法打开日志文件：" + filename);
    }
}

FileSink::~FileSink() {
    if (file_.is_open()) {
        file_.close();
    }
}

void FileSink::write(const LogEntry& entry) {
    std::lock_guard<std::mutex> lock(fileMutex_);
    
    file_ << "[" << Logger::formatTimestamp(entry.timestamp) << "] "
          << "[" << Logger::levelToString(entry.level) << "] "
          << "[" << entry.threadId << "] "
          << entry.message << std::endl;
}

void FileSink::flush() {
    std::lock_guard<std::mutex> lock(fileMutex_);
    file_.flush();
}

// Logger 实现
Logger& Logger::getInstance() {
    static Logger instance;
    return instance;
}

Logger::Logger() : level_(LogLevel::INFO), running_(false) {
    // 默认添加控制台输出
    addSink(std::make_shared<ConsoleSink>());
}

Logger::~Logger() {
    stopAsync();
    flushAll();
}

void Logger::addSink(std::shared_ptr<LogSink> sink) {
    std::lock_guard<std::mutex> lock(sinkMutex_);
    sinks_.push_back(sink);
}

void Logger::log(LogLevel level, const std::string& message) {
    if (level < level_) {
        return;
    }
    
    LogEntry entry(message, level);
    
    if (running_) {
        // 异步模式，添加到队列
        std::unique_lock<std::mutex> lock(queueMutex_);
        logQueue_.push(entry);
        lock.unlock();
        queueCondition_.notify_one();
    } else {
        // 同步模式，直接写入
        std::lock_guard<std::mutex> lock(sinkMutex_);
        for (auto& sink : sinks_) {
            sink->write(entry);
        }
    }
    
    // FATAL级别日志记录完后立即刷新并退出程序
    if (level == LogLevel::FATAL) {
        flushAll();
        std::exit(EXIT_FAILURE);
    }
}

void Logger::startAsync() {
    if (running_) {
        return;
    }
    
    running_ = true;
    asyncThread_ = std::thread(&Logger::processLogQueue, this);
}

void Logger::stopAsync() {
    if (!running_) {
        return;
    }
    
    running_ = false;
    queueCondition_.notify_one();
    
    if (asyncThread_.joinable()) {
        asyncThread_.join();
    }
}

void Logger::flushAll() {
    std::lock_guard<std::mutex> lock(sinkMutex_);
    for (auto& sink : sinks_) {
        sink->flush();
    }
}

void Logger::processLogQueue() {
    while (running_ || !logQueue_.empty()) {
        std::unique_lock<std::mutex> lock(queueMutex_);
        
        // 等待新的日志条目或停止信号
        queueCondition_.wait(lock, [this] {
            return !running_ || !logQueue_.empty();
        });
        
        // 将队列中的所有日志条目写入接收器
        while (!logQueue_.empty()) {
            LogEntry entry = logQueue_.front();
            logQueue_.pop();
            
            lock.unlock();
            
            std::lock_guard<std::mutex> sinkLock(sinkMutex_);
            for (auto& sink : sinks_) {
                sink->write(entry);
            }
            
            lock.lock();
        }
        
        // 每批日志写完后刷新
        lock.unlock();
        flushAll();
    }
}

std::string Logger::levelToString(LogLevel level) {
    switch (level) {
        case LogLevel::DEBUG:   return "DEBUG";
        case LogLevel::INFO:    return "INFO ";
        case LogLevel::WARNING: return "WARN ";
        case LogLevel::ERROR:   return "ERROR";
        case LogLevel::FATAL:   return "FATAL";
        default:                return "UNKN ";
    }
}

std::string Logger::formatTimestamp(const std::chrono::system_clock::time_point& time) {
    auto tt = std::chrono::system_clock::to_time_t(time);
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                  time.time_since_epoch()) % 1000;
    
    std::tm local_tm;
    localtime_r(&tt, &local_tm);
    
    std::ostringstream oss;
    oss << std::put_time(&local_tm, "%Y-%m-%d %H:%M:%S")
        << '.' << std::setfill('0') << std::setw(3) << ms.count();
    
    return oss.str();
}

} // namespace logger
} // namespace common 